﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IntegrationTest
{
    public abstract class MultiThreadTest:TestItem
    {


        private int Counter = 0;

        protected abstract int GetCount();

        protected override void OnExecute()
        {

            int count = GetCount();
            List<WaitItem> waitItems = new List<WaitItem>();
            int index = 0;
            while (count > 0)
            {
                WaitItem wi = new WaitItem();
                wi.Test = this;
                wi.Index = index;
                waitItems.Add(wi);
                index++;
                count--;
                if (waitItems.Count >= Threads)
                {
                    RunItems(waitItems);
                }
                
            }
            if (waitItems.Count > 0)
                RunItems(waitItems);
        }

        private void RunItems(List<WaitItem> waitItems)
        {
            try
            {
                Counter = waitItems.Count;             
                foreach (WaitItem item in waitItems)
                {
                   
                    System.Threading.ThreadPool.QueueUserWorkItem(ThreadExecute, item);
                }
                while (Counter > 0 && EndTime> DateTime.Now)
                {
                    System.Threading.Thread.Sleep(10);
                }
                foreach (WaitItem item in waitItems)
                {
                    if (item.Error != null)
                        throw item.Error;
                }
            }
            finally
            {
               
                waitItems.Clear();
            }
        }

        private void ThreadExecute(object state)
        {
            WaitItem wi = (WaitItem)state;
            try
            {
                OnThreadExecute(wi.Index);
            }
            catch (Exception e_)
            {
                wi.Error = e_;
            }
            finally
            {
                System.Threading.Interlocked.Decrement(ref wi.Test.Counter);
            }
        }

        protected abstract void OnThreadExecute(int Index);

        public int Threads
        {
            get;
            set;
        }

        public class WaitItem
        {

            public MultiThreadTest Test;

            public Exception Error;

            public int Index;

           
        }
    }
}
